package com.example.ywr.service.impl;

import com.example.ywr.common.PageParam;
import com.example.ywr.common.PageResult;
import com.example.ywr.entity.User;
import com.example.ywr.repository.UserRepository;
import com.example.ywr.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User register(User user) {
        // 检查用户名是否已存在
        Optional<User> existUser = userRepository.findByUsernameAndIsDeletedFalse(user.getUsername());
        if (existUser.isPresent()) {
            throw new RuntimeException("用户名已存在");
        }
        // 检查手机号是否已存在
        if (user.getPhone() != null) {
            existUser = userRepository.findByPhoneAndIsDeletedFalse(user.getPhone());
            if (existUser.isPresent()) {
                throw new RuntimeException("手机号已存在");
            }
        }
        // 检查邮箱是否已存在
        if (user.getEmail() != null) {
            existUser = userRepository.findByEmailAndIsDeletedFalse(user.getEmail());
            if (existUser.isPresent()) {
                throw new RuntimeException("邮箱已存在");
            }
        }
        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return userRepository.save(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User update(User user) {
        Optional<User> optional = userRepository.findById(user.getId());
        if (optional.isPresent()) {
            User existUser = optional.get();
            // 更新用户信息
            existUser.setNickname(user.getNickname());
            existUser.setPhone(user.getPhone());
            existUser.setEmail(user.getEmail());
            existUser.setAvatar(user.getAvatar());
            existUser.setGender(user.getGender());
            existUser.setBirthday(user.getBirthday());
            existUser.setStatus(user.getStatus());
            existUser.setRole(user.getRole());
            return userRepository.save(existUser);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id) {
        Optional<User> optional = userRepository.findById(id);
        if (optional.isPresent()) {
            User user = optional.get();
            user.setIsDeleted(true);
            userRepository.save(user);
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDelete(List<Long> ids) {
        List<User> users = userRepository.findAllById(ids);
        if (!users.isEmpty()) {
            users.forEach(user -> user.setIsDeleted(true));
            userRepository.saveAll(users);
            return true;
        }
        return false;
    }

    @Override
    public User getById(Long id) {
        Optional<User> optional = userRepository.findById(id);
        return optional.orElse(null);
    }

    @Override
    public User getByUsername(String username) {
        Optional<User> optional = userRepository.findByUsernameAndIsDeletedFalse(username);
        return optional.orElse(null);
    }

    @Override
    public User getByPhone(String phone) {
        Optional<User> optional = userRepository.findByPhoneAndIsDeletedFalse(phone);
        return optional.orElse(null);
    }

    @Override
    public User getByEmail(String email) {
        Optional<User> optional = userRepository.findByEmailAndIsDeletedFalse(email);
        return optional.orElse(null);
    }

    @Override
    public PageResult<User> list(PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<User> page = userRepository.findAll(pageable);
        return PageResult.fromPage(page);
    }

    @Override
    public PageResult<User> listByUsername(String username, PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<User> page = userRepository.findByUsernameContainingAndIsDeletedFalse(username, pageable);
        return PageResult.fromPage(page);
    }

    @Override
    public PageResult<User> listByNickname(String nickname, PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<User> page = userRepository.findByNicknameContainingAndIsDeletedFalse(nickname, pageable);
        return PageResult.fromPage(page);
    }

    @Override
    public PageResult<User> listByRole(String role, PageParam pageParam) {
        Sort sort = Sort.by(Sort.Direction.fromString(pageParam.getOrderDirection()), 
                pageParam.getOrderBy() != null ? pageParam.getOrderBy() : "createTime");
        Pageable pageable = PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), sort);
        Page<User> page = userRepository.findByRoleAndIsDeletedFalse(role, pageable);
        return PageResult.fromPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(Long id, Integer status) {
        int rows = userRepository.updateStatus(id, status);
        return rows > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateStatus(List<Long> ids, Integer status) {
        int rows = userRepository.batchUpdateStatus(ids, status);
        return rows > 0;
    }

    @Override
    public User login(String username, String password) {
        Optional<User> optional = userRepository.findByUsernameAndIsDeletedFalse(username);
        if (optional.isPresent()) {
            User user = optional.get();
            if (passwordEncoder.matches(password, user.getPassword())) {
                // 更新最后登录时间
                user.setLastLoginTime(LocalDateTime.now());
                userRepository.save(user);
                return user;
            }
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePassword(Long id, String oldPassword, String newPassword) {
        Optional<User> optional = userRepository.findById(id);
        if (optional.isPresent()) {
            User user = optional.get();
            if (passwordEncoder.matches(oldPassword, user.getPassword())) {
                user.setPassword(passwordEncoder.encode(newPassword));
                userRepository.save(user);
                return true;
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetPassword(Long id, String password) {
        Optional<User> optional = userRepository.findById(id);
        if (optional.isPresent()) {
            User user = optional.get();
            user.setPassword(passwordEncoder.encode(password));
            userRepository.save(user);
            return true;
        }
        return false;
    }
}